package cn.com.joycode.nimble.springboot.filter;

import cn.com.joycode.nimble.core.message.NbMsg;
import cn.com.joycode.nimble.core.utils.ObjectMapperUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpMethod;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * @author Max Woods
 */

@Slf4j
public class NbMsgFilter implements Filter {

    private static class NbMsgServletWrappser extends HttpServletRequestWrapper {

        private byte[] data;

        private NbMsgServletWrappser(HttpServletRequest request) {
            super(request);
            try {
                data = IOUtils.toByteArray(request.getInputStream());
                // 忽略非POST请求
                if (!StrUtil.equalsIgnoreCase(request.getMethod(), HttpMethod.POST.name())) {
                    return;
                }
                // 非json请求不处理
                /*
                if (!StrUtil.equalsAnyIgnoreCase(request.getContentType(), MimeTypeUtils.APPLICATION_JSON_VALUE)) {
                    return;
                }*/
                String body = new String(data, StandardCharsets.UTF_8);
                if (StrUtil.isNotBlank(body) && StrUtil.startWith(body, "{") && StrUtil.endWith(body, "}")) {
                    NbMsg nbMsg = ObjectMapperUtil.parseObject(body, NbMsg.class);
                    if (ObjectUtil.isNull(nbMsg)) {
                        return;
                    }
                    String ip = ServletUtil.getClientIP(request);
                    nbMsg.getHeader().setClientIp(ip);
                    data = nbMsg.toString().getBytes(StandardCharsets.UTF_8);
                }
            } catch (Exception e) {
                log.error("获取请求数据异常", e);
            }
        }

        @Override
        public ServletInputStream getInputStream() {
            final ByteArrayInputStream bais = new ByteArrayInputStream(data);

            return new ServletInputStream() {
                @Override
                public boolean isFinished() {
                    return false;
                }

                @Override
                public boolean isReady() {
                    return false;
                }

                @Override
                public void setReadListener(ReadListener readListener) {

                }

                @Override
                public int read() {
                    return bais.read();
                }
            };
        }
    }


    @SuppressWarnings("cast")
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException, ClassCastException {
        if (!(request instanceof HttpServletRequest)) {
            chain.doFilter(request, response);
        }
        NbMsgServletWrappser nbMsgServletWrappser = new NbMsgServletWrappser((HttpServletRequest) request);
        chain.doFilter(nbMsgServletWrappser, response);
    }
}